<template>
  <view
    class="button"
    :class="[
      `button--${type}`,
      `button--${size}`,
      `button--${shape}`,
      {
        'button--plain': plain,
        'button--block': block,
        'button--disabled': disabled,
        'button--loading': loading,
        'button--end': end,
        'button--gray': type === 'default' && invert,
        'button--shadow': shadowable,
      },
    ]"
    :style="[getStyle]"
    @click="handleClick"
  >
    <view class="button__wrap">
      <m-icon
        v-if="loading ? 'loading' : icon"
        :size="iconSize"
        :color="iconColor"
        :name="loading ? 'loading' : icon"
      ></m-icon>

      <view v-if="$slots.default" :class="{ text: icon }" class="button__inner">
        <slot></slot>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import { defineComponent, PropType, computed, toRefs } from '@vue/composition-api'
import addUnit from '@/utils/add-unit'
import addColor from '@/utils/add-color'

export type ButtonType = 'default' | 'primary' | 'text' | 'danger' | 'success' | 'info' | 'hermes'
export type ButtonSize = 'xl' | 'lg' | 'md' | 'sm' | 'xs'
export type ButtonShape = 'square' | 'round'
import throttle from '@/utils/throttle'

export default defineComponent({
  props: {
    color: {
      type: String,
      default: null,
    },
    background: {
      type: String,
      default: null,
    },
    shape: {
      type: String as PropType<ButtonShape>,
      default: 'square',
    },
    plain: {
      type: Boolean,
      default: false,
    },
    loading: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    type: {
      type: String as PropType<ButtonType>,
      default: 'primary',
    },
    size: {
      type: String as PropType<ButtonSize>,
      default: 'lg',
    },
    block: {
      type: Boolean,
      default: false,
    },
    icon: {
      type: String,
      default: '',
    },
    iconSize: {
      type: [Number, String],
      default: 40,
    },
    height: {
      type: String,
      default: null,
    },
    width: {
      type: String,
      default: null,
    },
    iconColor: {
      type: String,
      default: 'inherit',
    },
    end: {
      type: Boolean,
      default: false,
    },
    invert: {
      type: Boolean,
      default: false,
    },
    shadowable: {
      type: Boolean,
      default: false,
    },
    padding: {
      type: String,
      default: null,
    },
    borderColor: {
      type: String,
      default: null,
    },
    // 节流，一定时间内只能触发一次
    throttleTime: {
      type: [String, Number],
      default: 1000,
    },
  },
  options: {
    styleIsolation: 'shared',
    virtualHost: true, //  将自定义节点设置成虚拟的，更加接近Vue组件的表现。我们不希望自定义组件的这个节点本身可以设置样式、响应 flex 布局等，而是希望自定义组件内部的第一层节点能够响应 flex 布局或者样式由自定义组件本身完全决定
  },
  setup(props, { emit }) {
    const { disabled, loading, background, color, height, width, end, padding, borderColor } = toRefs(props)

    const handleClick = (event: MouseEvent) => {
      if (loading.value || disabled.value || end.value) {
        return
      }

      // 进行节流控制，每this.throttle毫秒内，只在开始处执行
      throttle(() => {
        emit('click', event)
      }, props.throttleTime)
    }

    const getStyle = computed(() => {
      const style: any = {}

      if (background?.value) {
        style.background = addColor(background.value)
      }

      if (color?.value) {
        style.color = addColor(color.value)
      }

      if (height?.value) {
        style.height = addUnit(height.value)
      }

      if (width?.value) {
        style.width = addUnit(width.value)
      }
      if (padding?.value) {
        style.padding = addUnit(padding.value)
      }
      if (borderColor?.value) {
        style.borderColor = addUnit(borderColor.value)
      }
      return style
    })

    return {
      handleClick,
      getStyle,
    }
  },
})
</script>
<style lang="scss" scoped>
.button {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
  box-sizing: border-box;
  text-align: center;
  cursor: pointer;
  transition: opacity 0.2s;
  -webkit-appearance: none;
  user-select: none;
  touch-action: manipulation;

  ::v-deep {
    .icon--loading {
      display: block;
    }
  }

  &--shadow {
    box-shadow: 0rpx 4rpx 26rpx 0rpx rgba(208, 74, 74, 0.5);
  }

  .text {
    margin-left: 10rpx;
  }

  &::before {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    background-color: #000;
    border: inherit;
    border-color: #000;
    border-radius: inherit;
    transform: translate(-50%, -50%);
    opacity: 0;
    content: ' ';
  }

  &:active::before {
    opacity: 0.1;
  }

  &__wrap {
    height: 100%;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  &--loading,
  &--disabled {
    &::before {
      display: none;
    }
  }

  &--default {
    color: $--font-primary-c;
    background: $--bg-content-c;
    border-width: 0;
  }

  &--primary {
    color: $--white-c;
    background: $--btn-primary-bgc;
    border-width: 0;
  }

  &--info {
    color: #fff;
    background: $--btn-info-bgc;
    border-width: 0;
  }

  &--warning {
    color: $--white-c;
    background: $--btn-warning-bgc;
    border-width: 0;
  }

  &--success {
    color: $--white-c;
    background: $--btn-success-bgc;
    border-width: 0;
  }

  &--danger {
    color: $--white-c;
    background: $--danger-c;
    border-width: 0;
  }

  &--gray {
    color: $--font-primary-c;
    background: $--bg-body-c;
    border-width: 0;
  }

  &--text {
    color: $--font-primary-c;
  }

  &--plain {
    background: $--bg-content-c;
    border-width: 1rpx;
    border-style: solid;

    &.button--default {
      border-color: #d9d9d9;
    }

    &.button--primary {
      color: $--primary-c;
      border-color: $--primary-c;
      background: #f0fafe;
    }

    &.button--info {
      color: $--info-c;
      border-color: $--info-c;
    }

    &.button--warning {
      color: $--warning-c;
      border-color: $--warning-c;
      background: #fffaf2;
    }

    &.button--success {
      color: $--success-c;
      border-color: $--success-c;
      background: #f0fdf7;
    }

    &.button--danger {
      color: $--danger-c;
      border-color: $--info-c;
      background: #fff4f1;
    }

    &.button--gray {
      background-color: $--white-c;
      border-color: $--bd-dark-c;
    }
  }

  &--hermes {
    display: block;
    margin: 0 auto;
    height: 89rpx;

    .button__wrap {
      position: relative;

      &::before {
        position: absolute;
        content: '';
        top: 7rpx;
        left: 0;
        right: 0;
        height: 82rpx;
        background: linear-gradient(270deg, #f49443 0%, #fc8e3a 100%);
        box-shadow: 0rpx 2rpx 10rpx 0rpx rgba(218, 180, 135, 0.5);
        border-radius: 41rpx;
      }

      &::after {
        position: absolute;
        content: '';
        top: 0;
        left: 0;
        right: 0;
        height: 82rpx;
        background: linear-gradient(180deg, #f9ec7b 0%, #f6b84a 100%);
        box-shadow: 0rpx 2rpx 10rpx 0rpx rgba(218, 180, 135, 0.5);
        border-radius: 41rpx;
      }
    }

    .button__inner {
      position: relative;
      z-index: 2;
      padding: 16rpx 0;
      text-align: center;
      color: #ba3612;
      font-size: 36rpx;
    }
  }

  &--xl {
    @include fz32;
    width: 100%;
    margin-right: 0;
    line-height: $--btn-xl-h;
    border-radius: $--btn-xl-bdrd;
    padding: $--btn-xl-p;
  }

  &--lg {
    font-size: 38rpx;
    line-height: $--btn-lg-h;
    border-radius: $--btn-lg-bdrd;
    padding: $--btn-lg-p;
  }

  &--md {
    @include fz28;
    line-height: $--btn-md-h;
    border-radius: $--btn-md-bdrd;
    padding: $--btn-md-p;
  }

  &--sm {
    @include fz24;
    line-height: $--btn-sm-h;
    border-radius: $--btn-sm-bdrd;
    padding: $--btn-sm-p;
  }

  &--xs {
    @include fz20;
    transform-origin: left center;
    line-height: $--btn-xs-h;
    border-radius: $--btn-xs-bdrd;
    padding: $--btn-xs-p;
  }

  &--block {
    display: block;
    width: 100%;
    margin-right: 0;
  }

  &--disabled {
    cursor: not-allowed;
    opacity: 0.3;
  }

  &--loading {
    cursor: default;
    opacity: 0.3;
  }

  &--round {
    border-radius: $--btn-round-bdrd;
    padding: 0 16rpx;
  }

  &--angle {
    border-radius: 0rpx;
  }

  &--end {
    background: #d9d9d9 !important;
    border-width: 0 !important;
    color: #fff !important;
    opacity: 1 !important;
    cursor: not-allowed;
  }
}
</style>
